/***************************************************************
|	File:		GameplayState.cpp
|	Author:		
|	Course:		
|	Purpose:	GameplayState class initializes & runs the game logic
***************************************************************/

#include "GameplayState.h"

#include "Game.h"
#include "MainMenuState.h"

#include "../SGD Wrappers/SGD_AudioManager.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "../SGD Wrappers/SGD_InputManager.h"
#include "../SGD Wrappers/SGD_String.h"

#include "../SGD Wrappers/SGD_EventManager.h"
#include "../SGD Wrappers/SGD_Event.h"
#include "../SGD Wrappers/SGD_MessageManager.h"
#include "../SGD Wrappers/SGD_Message.h"
#include "MessageID.h"

#include "Entity.h"
#include "EntityManager.h"

#include <cstdlib>
#include <cassert>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>


/**************************************************************/
// GetInstance
//	- allocate static global instance
//	- return THE instance
/*static*/ GameplayState* GameplayState::GetInstance( void )
{
	static GameplayState s_Instance;	// stored in global memory once
	return &s_Instance;
}


/**************************************************************/
// Enter
//	- reset game
//	- load resources
//	- set up entities
/*virtual*/ void GameplayState::Enter( void )	/*override*/
{
	// Set background color
	SGD::GraphicsManager::GetInstance()->SetClearColor( {0, 0, 0} );	// black

	// Initialize the Event & Message Managers
	SGD::EventManager::GetInstance()->Initialize();
	SGD::MessageManager::GetInstance()->Initialize( &MessageProc );


	// Allocate the Entity Manager
	m_pEntities = new EntityManager;


}


/**************************************************************/
// Exit
//	- deallocate entities
//	- unload resources
/*virtual*/ void GameplayState::Exit( void )	/*override*/
{



	// Deallocate the Entity Manager
	m_pEntities->RemoveAll();
	delete m_pEntities;
	m_pEntities = nullptr;
	

	// Terminate & deallocate the SGD wrappers
	SGD::EventManager::GetInstance()->Terminate();
	SGD::EventManager::DeleteInstance();

	SGD::MessageManager::GetInstance()->Terminate();
	SGD::MessageManager::DeleteInstance();
}


/**************************************************************/
// Update
//	- handle input & update entities
/*virtual*/ bool GameplayState::Update( float elapsedTime )	/*override*/
{
	SGD::InputManager* pInput = SGD::InputManager::GetInstance();
		
	// Press Escape to return to Main Menu
	if( pInput->IsKeyPressed( SGD::Key::Escape ) == true )
	{
		// ChangeState is VERY VOLATILE!!!
		//	- can only be safely called by a game state's
		//	  Update or Render methods!
		Game::GetInstance()->ChangeState( MainMenuState::GetInstance() );
		
		// Exit this state immediately
		return true;	// keep playing in the new state
	}


	// Update the entities
	m_pEntities->UpdateAll( elapsedTime );

	// Process the events & messages
	SGD::EventManager::GetInstance()->Update();
	SGD::MessageManager::GetInstance()->Update();
	
	return true;	// keep playing
}


/**************************************************************/
// Render
//	- render the game entities
/*virtual*/ void GameplayState::Render( float elapsedTime )	/*override*/
{
	// Render the entities
	m_pEntities->RenderAll();
}


/**************************************************************/
// MessageProc
//	- process messages queued in the MessageManager
//	- STATIC METHOD
//		- does NOT have invoking object!!!
//		- must use singleton to access members
/*static*/ void GameplayState::MessageProc( const SGD::Message* pMsg )
{
/* Show warning when a Message ID enumerator is not handled */
#pragma warning( push )
#pragma warning( 1 : 4061 )

	// What type of message?
	switch( pMsg->GetMessageID() )
	{
		default:
		case MessageID::MSG_UNKNOWN:
		{
			OutputDebugStringW( L"Game::MessageProc - unknown message id\n" );
		}
		break;
	
	
	}

/* Restore previous warning levels */
#pragma warning( pop )
}
